﻿using System;
using System.Collections.Generic;
using System.Text;
using AMStudio.Script;

namespace IPTE.Manager
{
    public enum PCICard_PORT_TYPE
    {
        Input,
        Output,
        Both
    }
    public enum PCICard_DATA_TYPE
    {
        Bit,
        Byte
    }
    public class PCICardDIO
    {
        public readonly string Name;
        public readonly string ModName;
        public readonly int Start_Addr;
        public readonly int Bit_Address;
        public readonly int Data_Len;
        public readonly PCICard_PORT_TYPE Port_Type;
        public readonly PCICard_DATA_TYPE Data_Type;
        public readonly int Card;
        public readonly string Comments;

        public bool BitValue;
        public byte[] ByteValue;

        public PCICardDIO(string name, string modName, int port, int index, int len, PCICard_PORT_TYPE portType, PCICard_DATA_TYPE dataType, int card, string readMode, string comments)
        {
            this.Name = name;
            this.ModName = modName;
            Start_Addr = port;
            Bit_Address = index;
            Data_Len = len;
            Port_Type = portType;
            Data_Type = dataType;
            this.Card = card;
            this.Comments = comments;
            this.ReadMode = readMode;
            ByteValue = new byte[len];
        }

        //below is for script support
        public readonly string ReadMode;
        public bool AlreadyReadForCycle;
        public void GetSubCellValue(PCICardDIO subCell)
        {
            int offset = subCell.Start_Addr - this.Start_Addr;
            subCell.ByteValue = new byte[subCell.Data_Len];
            Array.Copy(this.ByteValue, offset, subCell.ByteValue, 0, subCell.Data_Len);
            subCell.BitValue = subCell.GetSubBitBoolValue(subCell.Bit_Address);
        }
        public bool GetSubBitBoolValue(int bitPosition)
        {
            int index = bitPosition / 8;
            int bitIndex = bitPosition % 8;
            bitIndex = 1 << bitIndex;
            if ((this.ByteValue[index] & bitIndex) > 0)
            {
                return true;
            }
            return false;
        }
    }


    public class PCICardByteCell : PCICardDIO, IRefrenceValueTag<Byte>
    {
        private IRefrenceTagProvider provider = null;

        public IRefrenceTagProvider TagProvider
        {
            get
            {
                return this.provider;
            }
            set
            {
                this.provider = value;
            }
        }

        public Byte Value
        {
            get
            {
                provider.ReadTag(this);
                return this.ByteValue[0];
            }
            set
            {
                this.ByteValue[0] = value;
                provider.WriteTag(this);
            }
        }
        public override string ToString()
        {
            return this.Value.ToString();
        }

        public PCICardByteCell(string name, string modName, int port, int index, int len, PCICard_PORT_TYPE portType, PCICard_DATA_TYPE dataType, int card, string readMode, string comments)
            : base(name, modName, port, index, len, portType, dataType, card, readMode, comments)
        {
        }
    }
    public class PCICardBoolCell : PCICardDIO, IRefrenceValueTag<bool>
    {
        private IRefrenceTagProvider provider = null;
        public IRefrenceTagProvider TagProvider
        {
            get
            {
                return this.provider;
            }
            set
            {
                this.provider = value;
            }
        }

        public bool Value
        {
            get
            {
                provider.ReadTag(this);
                return this.BitValue;
            }
            set
            {
                this.BitValue = value;
                provider.WriteTag(this);
            }
        }
        public override string ToString()
        {
            return this.Value.ToString();
        }

        public PCICardBoolCell(string name, string modName, int port, int index, int len, PCICard_PORT_TYPE portType, PCICard_DATA_TYPE dataType, int card, string readMode, string comments)
            : base(name, modName, port, index, len, portType, dataType, card, readMode, comments)
        {
        }

    }
    public class PCICardByteArrayCell : PCICardDIO, IRefrenceValueTag<Byte[]>
    {
        private IRefrenceTagProvider provider = null;

        public IRefrenceTagProvider TagProvider
        {
            get
            {
                return this.provider;
            }
            set
            {
                this.provider = value;
            }
        }

        public Byte[] Value
        {
            get
            {
                provider.ReadTag(this);
                return this.ByteValue;
            }
            set
            {
                this.ByteValue = value;
                provider.WriteTag(this);
            }
        }
        public override string ToString()
        {
            StringBuilder str = new StringBuilder();
            Byte[] v = this.Value;
            for (int i = 0; i < this.Data_Len; i++)
            {
                str.Append(v[i].ToString());
            }
            return base.ToString();
        }

        public PCICardByteArrayCell(string name, string modName, int port, int index, int len, PCICard_PORT_TYPE portType, PCICard_DATA_TYPE dataType, int card, string readMode, string comments)
            : base(name,  modName,port, index, len, portType, dataType, card, readMode, comments)
        {
        }
    }
}
